import java.util.List;
import java.util.Iterator;
import java.util.Random;

/**
 * A simple model of a fox.
 * Foxes age, move, eat rabbits, and die.
 * 
 * @author David J. Barnes and Michael Kolling
 * @version 2008.03.30
 */
public class Hunter implements Actor
{
	// Whether the animal is alive or not.
    private boolean active;
    // The animal's field.
    private Field field;
    // The animal's position in the field.
    private Location location;
	
	// Characteristics shared by all hunters (static fields)
    //The highest experience level a hunter can have.
    private static final int MAX_EXPLEVEL = 10;
    // The time a player can hunt.
    private static final int MAX_DURATION = 10000;
    // A shared random number generator to control breeding.
    private boolean isHunted = false;
    
    // Individual characteristics (instance fields).
    // The fox's age.
    private int duration;
    // The fox's food level, which is increased by eating rabbits.
    //private int foodLevel;
    private int experience; //experience level from 1 to 10
    private int bulletAmount; //bulletamount from min 10 to max 20

    /**
     * Create a fox. A fox can be created as a new born (age zero
     * and not hungry) or with a random age and food level.
     * 
     * @param randomAge If true, the fox will have random age and hunger level.
     * @param field The field currently occupied.
     * @param location The location within the field.
     */
    public Hunter(boolean randomDuration, Field field, Location location)
    {
    	this.active = true;
        this.field = field;
        setLocation(location);
        if(randomDuration) {
            duration = new Random().nextInt(MAX_DURATION)+1000;
            experience = new Random().nextInt(MAX_EXPLEVEL);
            bulletAmount = new Random().nextInt(1000000) + 10;
        }
        else {
            duration = 1000;
            experience = 1;
            bulletAmount = 1000000;
        }
    }
    
    /**
     * This is what the fox does most of the time: it hunts for
     * rabbits. In the process, it might breed, die of hunger,
     * or die of old age.
     * @param field The field currently occupied.
     * @param newFoxes A list to add newly born foxes to.
     */
    public void act(List<Actor> newHunters)
    {
        incrementDuration();
        if(isActive()) {   
            // Move towards a source of food if found.
            Location location = getLocation();
            Location newLocation = findVictim(location);
            if(newLocation == null) { 
                // No food found - try to move to a free location.
                newLocation = getField().freeAdjacentLocation(location);
            }
            // See if it was possible to move.
            if(newLocation != null) {
                setLocation(newLocation);
            }
            else {
                // Overcrowding.
                setInactive();
            }
        }
    }

    /**
     * Decrease the amount of bullets a hunter has.
     */
    private void decrementBullet()
    {
        bulletAmount--;
        if(bulletAmount <= 0) {
            setInactive();
        }
    }
    
    /**
     * Increase the durationamount for the hunter
     */
    private void incrementDuration()
    {
        duration++;
        if(duration > MAX_DURATION) {
        	setInactive();
        }
    }
    
    /**
     * Tell the fox to look for rabbits adjacent to its current location.
     * Only the first live rabbit is eaten.
     * @param location Where in the field it is located.
     * @return Where food was found, or null if it wasn't.
     */
    private Location findVictim(Location location) 
    {
        assert location != null : "Null location passed to adjacentLocations";
        Field field = getField();
        List<Location> adjacent = field.adjacentLocations(getLocation());
        Iterator<Location> it = adjacent.iterator();
        while(it.hasNext()) {
            Location where = it.next();
            Object animal = field.getObjectAt(where);
            if(animal instanceof Fox /*|| animal instanceof Rabbit*/) {
            	if (FieldStats.getAnimalAmount(Fox.class) > 100) {
            		Fox fox = (Fox) animal;
                
                		if(fox.isActive()) { 
                			fox.setDead();
                			duration += 10;
                			//decrementBullet();
                    	// Remove the dead fox from the field.
                		return where;
                		}
            	} else if (animal instanceof Rabbit) {
            		Rabbit rabbit = (Rabbit) animal;
            			if(rabbit.isActive()) {
            				rabbit.setDead();
            				duration+= 10;
            			//Remove the dead rabbit from the field
            			return where;
            			}
            	} else if (animal instanceof Hunter) {
            		Hunter hunter = (Hunter) animal;
            			if(hunter.isActive()) {
            				if(bulletAmount <= 0) {
            					hunter.setInactive();
            				}
            			}
            	}
            } else {
            	//wait for value changes
            }
        }
        return null;
    }
    
    public void setHunted() {
    	if (!isHunted) {
    		isHunted = true;
    	}
    	   
    }

    public void unsetHunted() {
    	isHunted = false;
    }
    
    public boolean isHunted() {
    	return isHunted;
    } 
    
    /**
     * Check whether the animal is alive or not.
     * @return true if the animal is still alive.
     */
    public boolean isActive()
    {
        return active;
    }

    /**
     * Indicate that the animal is no longer alive.
     * It is removed from the field.
     */
    public void setInactive()
    {
        active = false;
        if(location != null) {
            field.clear(location);
            location = null;
            field = null;
        }
    }

    /**
     * Return the animal's location.
     * @return The animal's location.
     */
    public Location getLocation()
    {
        return location;
    }
    
    /**
     * Return the animal's field.
     * @return The animal's field.
     */
    public Field getField()
    {
        return field;
    }
    
    /**
     * Place the animal at the new location in the given field.
     * @param newLocation The animal's new location.
     */
    public void setLocation(Location newLocation)
    {
        if(location != null) {
            field.clear(location);
        }
        
        location = newLocation;
        field.place(this, newLocation);
    }
}

